Skip to content

restrict amazon-bedrock provider to curated model allowlist#15

Open
lgarceau768 wants to merge 38 commits intoflexfrom
task/bedrock-model-allowlist
Open

restrict amazon-bedrock provider to curated model allowlist#15
lgarceau768 wants to merge 38 commits intoflexfrom
task/bedrock-model-allowlist

Conversation

@lgarceau768
Copy link
Copy Markdown
Collaborator

Issue for this PR

Closes #

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds a hardcoded BEDROCK_ALLOWED_MODELS set in packages/opencode/src/provider/provider.ts that restricts the amazon-bedrock provider to a curated list of 30 approved models. The filter runs inside the existing provider initialization loop, immediately after the deprecated status check and before the config blacklist/whitelist check.

Approved models by family:

  • Anthropic/Claude: Sonnet 4.6 (US), Opus 4.6 (US), Haiku 4.5 (US)
  • Google Gemma (Bedrock): 27B, 12B, 4B
  • OpenAI/GPT (Bedrock): GPT Safeguard 120B, GPT Safeguard 20B
  • Amazon Nova: Nova 2 Lite
  • Qwen: 235B, 80B, 32B, Coder 30B
  • NVIDIA Nemotron: Nano 30B, Nano 12B, Nano 9B
  • Mistral: Large 675B, Magistral Small, Ministral 14B, Ministral 8B, Voxtral 24B
  • DeepSeek: R1
  • Minimax: M2
  • Moonshot/Kimi: K2 (kimi-k2.5), K2 Thinking
  • ZAI/GLM: GLM-4.7, GLM-4.7 Flash
  • Writer/Palmyra: X5, X4
  • Meta/Llama: Llama 3.1 8B

Because the built-in allowlist runs before the config-level whitelist/blacklist, users can still add custom models (e.g. a Bedrock fine-tune) via their opencode config without being blocked.

How did you verify your code works?

  • Ran bun typecheck in packages/opencode — passes clean.
  • Verified the 30 model IDs against the current models-snapshot.js to confirm each entry exists and maps to the expected model.

Screenshots / recordings

N/A — no UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

lgarceau768 and others added 30 commits April 15, 2026 12:09
Mark the skill template TextPart as synthetic so the full prompt is
sent to the model but hidden from the user. Add a short ignored
summary part ('Running skill: <command>') so the user still sees
confirmation that the skill was loaded.

Rebased from flexion/hide-skill-prompt-in-chat onto v1.4.0.
Gate tool resolution, LiteLLM noop injection, activeTools, tools, and
toolChoice behind input.model.capabilities.toolcall. Without this fix,
tool_call: false in opencode.json is parsed and stored but never checked,
causing Bedrock models that don't support streaming + tool use to fail.

Adds regression test verifying body.tools is not sent when toolcall: false.

Cherry-picked from lgarceau768#1 and rebased onto v1.4.0.
Covers cloning, building with bun, AWS SSO profile config,
opencode.json Bedrock provider setup, and the opencode-work
shell alias. Notes the tool_call fix included in this branch.
Bun's embedded code signature is rejected by Darwin 25+ at runtime,
killing the binary with SIGKILL (exit 137) before it starts. Strip the
signature and apply a fresh ad-hoc one via codesign after each darwin
build. Also documents the fix in LOCAL_AWS_SETUP.md.
fix: re-sign macOS binaries after Bun compile to fix Darwin 25+ SIGKILL
…ditional models

- Add palmyra and pixtral to US cross-region inference profile prefix list
- Strip reasoning content from message history for non-reasoning models
- Exclude palmyra from reasoning variant generation to prevent unsupported params
chore - merge dev into flex, resolve conflicts in session/llm.ts and session/prompt.ts
…o flex

# Conflicts:
#	packages/opencode/src/provider/provider.ts
#	packages/opencode/src/provider/transform.ts
Resolves duplicate module instances (0.1.99 vs 0.1.101) that caused
opentui-spinner to register the spinner component in a different
componentCatalogue than the one the reconciler uses, resulting in
"[Reconciler] Unknown component type: spinner" at runtime.
- add install-flex: single curl | bash installer that clones the flex
  branch, builds the binary, writes the AWS SSO profile, writes
  ~/.config/opencode/opencode.json, and appends opencode-work() to
  the user's shell rc file; all steps are idempotent
- hardcode SSO start URL and us-east-2 SSO region; prompt only for
  account ID and preferred AWS region
- correct sso_role_name from AdministratorAccess to ClaudeCodeAccess
- fix opencode-work(): replace undeclared \${opencode_args[@]} with
  "\$@", replace hardcoded path and arch with runtime uname detection
- add Quick Install section to LOCAL_AWS_SETUP.md
…B fragmentation

Without this, every build bakes the current git branch name as the installation
channel, causing OpenCode to open a new empty SQLite database each time you
rebuild from a different branch (opencode-chore-bolster-install.db,
opencode-feat-mcp-awareness.db, etc). Setting OPENCODE_CHANNEL=flex means all
Flexion fork builds share opencode-flex.db regardless of which branch was built.
…unners

Blacksmith's ubuntu-2404 runners run on ARM64 hardware (RUNNER_ARCH=ARM64).
The previous action only built an explicit bun download URL for X64, so ARM64
fell through to oven-sh/setup-bun@v2's default path which downloads
bun-linux-aarch64.zip and extracts it via the system unzip command. Blacksmith's
ARM64 Ubuntu image doesn't pre-install unzip, causing all e2e and unit CI jobs
to fail at the Setup Bun step.

Two changes:
- Add a Linux step that installs unzip if not already present (direct fix)
- Rewrite the URL construction with case/esac covering both X64 and ARM64 for
  all OS variants, replacing the x64-only if block (architecture fix)
…ion on ARM64

tree-sitter-powershell builds a native addon via node-gyp during bun install.
Blacksmith ARM64 runners don't pre-install make or g++, so the build fails with:

  gyp ERR! not found: make

Extend the prerequisite step to also check for make and install build-essential
(which provides make + g++) when missing, alongside the existing unzip check.
…in test timeouts

Plugin integration tests (auth-override, plugin config providers) each create a
fresh temp dir and trigger @npmcli/arborist to install @opencode-ai/plugin from
the npm registry. On Blacksmith ARM64, this network fetch takes 10-30 s per
test, consistently hitting the 30 s bun test timeout.

Two changes to the unit job in test.yml:
- Cache ~/.npm across runs so arborist finds tarballs locally on repeat runs
- Pre-warm step: npm install @opencode-ai/plugin once before tests run, which
  populates ~/.npm so arborist's per-test installs resolve from cache (~0.5 s)
  rather than the network (~10-30 s)
…t timeout

Root cause of all 7 test timeouts:

  config.ts fires a background @npmcli/arborist.reify() for @opencode-ai/plugin
  in every .opencode/ directory it discovers. plugin/index.ts and tool/registry.ts
  then call waitForDependencies() which joins that fiber before loading plugins
  or custom tools. On Blacksmith ARM64, a cold arborist fetch takes 10-30 s per
  test. Running in parallel across a 4-vCPU runner saturates CPU/IO and starves
  even unrelated tests (session.processor, snapshot.revert) past their 30 s limit.

Fixes:
  - flag.ts: add OPENCODE_DISABLE_PLUGIN_DEPS_INSTALL flag
  - config.ts: guard the npmSvc.install() + deps.push() block with the new flag
  - preload.ts: set OPENCODE_DISABLE_PLUGIN_DEPS_INSTALL=true for all tests
    (safe: bun resolves @opencode-ai/plugin from the workspace node_modules;
    tests do not author plugins that import the SDK at runtime)
  - snapshot.test.ts: raise timeout on the 280-file revert test to 60 s
    (git operations across 280 files can push past 30 s on ARM64)
Blacksmith ARM64 runner subprocess startup overhead can consume 2-3 s,
pushing the 'loop waits while shell runs' test past its 3 s failsafe.
The test validates ordering (loop waits while shell is running), not wall
time, so a larger timeout doesn't change what is being tested.
chore: add install-flex, fix Blacksmith ARM64 CI (build tools + test timeouts), fix per-branch DB
…isks

Address all findings from security review:

- (High/F1) Replace perl s|...|...| substitution with printf %q heredoc to
  eliminate Perl injection via CLONE_DIR containing | or ; characters
- (High/F2) Validate all user inputs: CLONE_DIR blocked on shell metacharacters,
  ACCOUNT_ID enforced as exactly 12 digits, AWS_REGION validated against
  standard pattern; tilde expanded before use
- (Medium/F4) Add --frozen-lockfile to bun install so transitive versions are
  pinned to bun.lock, preventing silent upgrades when BUN_CONFIG_REGISTRY
  bypasses Artifactory
- (Medium/F5) Wrap eval + opencode invocation in a subshell so exported AWS
  credentials do not persist in the interactive shell after opencode exits
- (Medium/F6) Guard existing-clone path: abort on uncommitted changes or wrong
  branch; replace git checkout with merge --ff-only; add --depth 1 to fresh clone
- (Medium/F7) Replace cat >> ~/.aws/config heredoc with aws configure set calls
  for atomic, section-safe writes; use aws configure get for idempotency check
- (Low/F8) Verify aws-cli is v2 in check_prereqs; v1 produces an upgrade hint
- (Low/F9) grep -q regex on profile name replaced by aws configure get (F7)
- (Low/F10) Idempotency sentinel changed from function signature to fixed header
  comment, guarded with grep -qF
…permissions

- Add [[:cntrl:]] check to block newlines, tabs, and other control
  characters from CLONE_DIR input (per PR review comment)
- chmod 600 opencode.json after write so it is not world-readable
  (per PR review comment)
- Replace pre-commit with prek (Rust-based alternative)
- Update CONTRIBUTING.md with prek installation instructions
- Update .husky/pre-push to use prek command
- Add exclude pattern for JSON5 files (tsconfig.json, .oxlintrc.json)
- Remove Python 3.10+ requirement (prek is a single binary)

Benefits:
- Faster hook execution (Rust vs Python)
- No Python runtime dependency required
- Drop-in compatible with existing .pre-commit-config.yaml
- Better security features (SHA validation, cooldown periods)
fix: harden install-flex against injection, input validation, and supply-chain risks
Set autoupdate: false in the opencode.json written by install-flex so
the upstream version-check dialog does not appear on every session start
in the Flexion fork.
…ll-flex

chore - disable autoupdate in install-flex config
Adds a hardcoded BEDROCK_ALLOWED_MODELS Set in the provider
initialization loop that filters the amazon-bedrock provider
down to 30 approved models across Claude, Gemma, GPT Safeguard,
Nova 2 Lite, Qwen, Nemotron, Mistral, DeepSeek, Minimax, Kimi,
GLM, Palmyra, and Llama families.

The allowlist runs before the existing config blacklist/whitelist
check, so users can still override via config (e.g. to add a
custom Bedrock fine-tune).
@github-actions
Copy link
Copy Markdown

Hey! Your PR title restrict amazon-bedrock provider to curated model allowlist doesn't follow conventional commit format.

Please update it to start with one of:

  • feat: or feat(scope): new feature
  • fix: or fix(scope): bug fix
  • docs: or docs(scope): documentation changes
  • chore: or chore(scope): maintenance tasks
  • refactor: or refactor(scope): code refactoring
  • test: or test(scope): adding or updating tests

Where scope is the package name (e.g., app, desktop, opencode).

See CONTRIBUTING.md for details.

@github-actions
Copy link
Copy Markdown

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • No issue referenced. Please add Closes #<number> linking to the relevant issue.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

The allowlist check was incorrectly deleting models that users
explicitly added via config (provider["amazon-bedrock"].models).
Add a guard so the filter only applies to snapshot-sourced models,
not ones the user has explicitly defined in their opencode.json.
Fast-exiting commands (e.g. echo test) could produce (no output)
because Effect.forkScoped interrupted the stream consumer fiber
before it had a chance to process chunks buffered in the Node.js
readable pipe.

Fix by joining the fiber after the exit/abort/timeout race so all
buffered stdout/stderr is flushed into the accumulator list before
Effect.scoped disposes the scope.
@lgarceau768
Copy link
Copy Markdown
Collaborator Author

Rebuilt, tested locally and confirmed only the models within the model document - also FlexChat - are shown here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants